Skip to content

Implement skill synchronization system with CI enforcement#5

Closed
L1nusB wants to merge 11 commits into
mainfrom
sync_skills_across_integration
Closed

Implement skill synchronization system with CI enforcement#5
L1nusB wants to merge 11 commits into
mainfrom
sync_skills_across_integration

Conversation

@L1nusB

@L1nusB L1nusB commented Mar 7, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Automated synchronization of GitNexus skills across integration targets.
    • Added gitnexus-pr-review to available skills.
  • Documentation

    • Comprehensive master guide for skill synchronization.
    • Reformatted and standardized skill docs across targets.
  • Tests

    • Extensive unit tests covering sync planning and behaviors.
  • Chores

    • CI verification job to enforce skill sync.
    • Added per-target manifest files and sync scripts.

L1nusB added 10 commits March 7, 2026 14:07
Reconcile all 4 skill locations to match gitnexus/skills/ (single source of truth):

- .claude/gitnexus-cli: restore missing PostToolUse hook sentence
- .claude/*: normalize formatting to match source exactly
- gitnexus-claude-plugin/gitnexus-cli: restore PostToolUse sentence + table formatting
- gitnexus-cursor-integration: restore canonical frontmatter descriptions (4 skills)
- gitnexus-cursor-integration: add missing gitnexus-cli and gitnexus-guide skills
- setup.ts: add gitnexus-pr-review to SKILL_NAMES (was missing, 6→7)

All 28 derived SKILL.md files are now byte-identical to their canonical source.
Companion files (mcp.json) are untouched.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc881-481d-702f-a7e4-448636bce3e1
Add 35 tests across 10 groups (T1–T10) for the planSync() function:
- T1: Source discovery (4 tests)
- T2: Target allowlist filtering (5 tests)
- T3: Content transformation (6 tests)
- T4: Path generation (3 tests)
- T5: Idempotency and skip detection (4 tests)
- T6: Companion file preservation (2 tests)
- T7: Error handling (2 tests)
- T8: Integration with actual repo state (3 tests)
- T9: SKILL_NAMES parity (2 tests)
- T10: Manifest validation (4 tests)

Includes a minimal stub at src/sync-skills.ts exporting the planSync
function signature, SyncTarget, and SyncOperation types. The stub
throws 'not yet implemented' so all tests that exercise planSync
fail (29 failing, 6 passing on repo-state/parity assertions).

All 839 existing unit tests remain green.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc883-d09d-7585-9168-614d57fb5845
Implement the core planSync() pure function that reads canonical skill
files from gitnexus/skills/ and plans write operations for derived targets.

Capabilities:
- Source discovery with gitnexus-* pattern filtering
- Target allowlist filtering with deduplication
- YAML frontmatter stripping (preserves mid-document --- rules)
- Generated header prepend (AUTO-GENERATED ... DO NOT EDIT)
- Trailing newline normalization
- Path generation: flat .md → {name}/SKILL.md
- Idempotency via content comparison (write/skip actions)
- Input validation (invalid skills array, missing source skills)
- Graceful handling of malformed frontmatter

TDD green phase: all 35 sync-skills tests pass.
Full unit suite: 874 tests passing.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc887-70da-7095-a050-1a52ec8a362d
…t — Phase 4 complete

- Create skills.manifest.json in all 3 target directories, each listing
  all 7 skills (including previously missing gitnexus-cli and gitnexus-guide
  in cursor integration)
- Create gitnexus/scripts/sync-skills.ts CLI runner that reads manifests,
  calls planSync(), and writes derived SKILL.md files
- Add npm scripts: sync:skills (run sync) and sync:skills:check (CI mode)
- Regenerate all 21 derived SKILL.md files with AUTO-GENERATED headers
- Verify idempotency (second run = 0 writes)
- Companion mcp.json files are untouched

Amp-Thread-ID: https://ampcode.com/threads/T-019cc887-70da-7095-a050-1a52ec8a362d
…omplete

Add a new CI job that runs npm run sync:skills then git diff --exit-code
on all 3 target directories. PRs that modify canonical skills without
running the sync script will fail CI.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc887-70da-7095-a050-1a52ec8a362d
Mark document status as complete. Verified sync is clean (21 files
up-to-date, git diff exit-code 0). All 874 unit tests passing.
Superseded analysis docs already removed in prior commit.

Amp-Thread-ID: https://ampcode.com/threads/T-019cc887-70da-7095-a050-1a52ec8a362d
@coderabbitai

coderabbitai Bot commented Mar 7, 2026

Copy link
Copy Markdown

Walkthrough

Adds a skills synchronization system: canonical skill sources, per-target manifests, a pure planSync implementation and CLI sync script, comprehensive unit tests, reformatted/auto-generated SKILL.md files, new manifests, package scripts, and a GitHub Actions job to verify synchronization across three integration targets.

Changes

Cohort / File(s) Summary
Canonical skills
gitnexus/skills/*, gitnexus/skills/*.md
Source skill markdown updated/created (formatting, fenced-blocks, minor workflow additions) and new/updated source files used as single source of truth.
.claude target
.claude/skills/gitnexus/*/SKILL.md, .claude/skills/gitnexus/skills.manifest.json
Added auto-generated headers and reformatted seven SKILL.md files; added .claude manifest listing all skills.
Claude plugin target
gitnexus-claude-plugin/skills/*/SKILL.md, gitnexus-claude-plugin/skills/skills.manifest.json
Replaced YAML front-matter with auto-generated comments in SKILL.md files; added per-target manifest enumerating skills.
Cursor integration target
gitnexus-cursor-integration/skills/*/SKILL.md, gitnexus-cursor-integration/skills/skills.manifest.json
Added/expanded SKILL.md documents (workflow, examples, tools) for multiple skills; added per-target manifest.
Sync implementation
gitnexus/src/sync-skills.ts, gitnexus/scripts/sync-skills.ts
New pure planSync API (exports SyncTarget/SyncOperation/planSync) and a CLI script that loads manifests, plans and performs writes (supports --dry-run).
CLI setup / SKILL_NAMES
gitnexus/src/cli/setup.ts
Extended SKILL_NAMES to include gitnexus-pr-review.
Tests
gitnexus/test/unit/sync-skills.test.ts
Added extensive unit tests (~700 lines) covering discovery, allowlists, transformations, idempotency, error cases, and integration checks.
Package scripts
gitnexus/package.json
Added npm scripts sync:skills and sync:skills:check to run the sync script and verification.
CI workflow
.github/workflows/ci.yml
Added skill-sync-check job that runs sync and verifies no skill files are out of sync via git diff.
Docs / process
docs/skill-sync.md, AGENTS.md, CLAUDE.md
Added comprehensive skill-sync design doc and updated agent/index references and guidance around sync process.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed Title check skipped as CodeRabbit has written the PR title.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Implement skill synchronization system with CI enforcement Mar 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md (1)

16-21: ⚠️ Potential issue | 🟡 Minor

Add fence languages here as well.

These example blocks are also emitted without a language tag, which makes the generated skill inconsistent with markdownlint's MD040 rule and the other typed blocks in this docset. Please fix the canonical source/generator rather than hand-editing this derived file.

Suggested fix
-```
+```text
 1. gitnexus_impact({target: "X", direction: "upstream"})  → What depends on this
 2. READ gitnexus://repo/{name}/processes                   → Check affected execution flows
 3. gitnexus_detect_changes()                               → Map current git changes to affected flows
 4. Assess risk and report to user
-```
+```

-```
+```text
 gitnexus_detect_changes({scope: "staged"})

 → Changed: 5 symbols in 3 files
 → Affected: LoginFlow, TokenRefresh, APIMiddlewarePipeline
 → Risk: MEDIUM
-```
+```

Please apply the same pattern to the remaining untyped fences in this skill.

Also applies to: 27-34, 57-71, 75-81, 85-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md` around
lines 16 - 21, The markdown has multiple code fences missing language tags
(e.g., the examples containing gitnexus_impact, READ
gitnexus://repo/{name}/processes, gitnexus_detect_changes, and the
gitnexus_detect_changes({scope: "staged"}) output block), causing MD040
violations; update the canonical generator/template so these specific fenced
blocks are emitted with an explicit language (use "text" for plain examples) and
apply the same fix to all other untyped fences referenced (lines corresponding
to the other example blocks), ensuring each fence around the example sequences
includes a language tag like ```text rather than leaving it untyped.
gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md (1)

15-21: ⚠️ Potential issue | 🟡 Minor

Emit language-tagged fences in the synced output.

This generated file still contains multiple unlabeled fenced blocks, so it will keep tripping MD040 until the canonical gitnexus-exploring source or the sync transform adds explicit languages like text.

Suggested fix
-```
+```text
 1. READ gitnexus://repos                          → Discover indexed repos
 2. READ gitnexus://repo/{name}/context             → Codebase overview, check staleness
 3. gitnexus_query({query: "<what you want to understand>"})  → Find related execution flows
 4. gitnexus_context({name: "<symbol>"})            → Deep dive on specific symbol
 5. READ gitnexus://repo/{name}/process/{name}      → Trace full execution flow
-```
+```

-```
+```text
 gitnexus_query({query: "payment processing"})
 → Processes: CheckoutFlow, RefundFlow, WebhookHandler
 → Symbols grouped by flow with file locations
-```
+```

Apply the same change to the other bare fences in this generated skill.

Also applies to: 27-34, 49-53, 57-62, 66-75

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md` around lines
15 - 21, The markdown contains multiple unlabeled fenced code blocks (e.g., the
block starting with "1. READ gitnexus://repos → Discover indexed repos" and the
block starting with 'gitnexus_query({query: "payment processing"})'), which
triggers MD040; update each bare triple-backtick fence in SKILL.md to include a
language tag (use "text") so they become ```text ... ```; ensure you apply the
same change to every other unlabeled fence in the file (including the other
examples referenced) so all fenced blocks are language-tagged consistently.
gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md (1)

15-20: ⚠️ Potential issue | 🟡 Minor

Add explicit languages to the generated fences.

These blocks are still emitted as bare triple-backtick fences, which markdownlint flags with MD040 here. Since this file is auto-generated, fixing only this copy will be overwritten; please add fence languages in the canonical skill or sync transform before regenerating.

Suggested fix
-```
+```text
 1. gitnexus_query({query: "<error or symptom>"})            → Find related execution flows
 2. gitnexus_context({name: "<suspect>"})                    → See callers/callees/processes
 3. READ gitnexus://repo/{name}/process/{name}                → Trace execution flow
 4. gitnexus_cypher({query: "MATCH path..."})                 → Custom traces if needed
-```
+```

-```
+```text
 - [ ] Understand the symptom (error message, unexpected behavior)
 - [ ] gitnexus_query for error text or related code
 - [ ] Identify the suspect function from returned processes
 - [ ] gitnexus_context to see callers and callees
 - [ ] Trace execution flow via process resource if applicable
 - [ ] gitnexus_cypher for custom call chain traces if needed
 - [ ] Read source files to confirm root cause
-```
+```

Apply the same change to the remaining untyped example blocks in this generated skill.

Also applies to: 26-34, 50-54, 58-63, 74-86

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md` around lines
15 - 20, The markdown code fences in SKILL.md are missing explicit languages
(markdownlint MD040); update the generated source (the canonical skill or the
sync transform that produces SKILL.md) to emit fenced blocks with a language
token (e.g., ```text) for the example lists that reference gitnexus_query,
gitnexus_context, READ gitnexus://..., and gitnexus_cypher so all occurrences
(the blocks around lines shown and the other untyped blocks at 26-34, 50-54,
58-63, 74-86) are rendered as ```text ... ``` instead of bare ``` ... ```,
ensuring the generator/template that builds SKILL.md emits the language token
rather than editing only this output file.
🧹 Nitpick comments (3)
.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md (1)

15-20: Consider adding language specifiers to pseudo-code blocks.

Same as noted for gitnexus-impact-analysis/SKILL.md: the workflow/checklist blocks could use ```text or ```plaintext to satisfy markdownlint (MD040) while accurately describing the non-executable nature of the content.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md around lines 15 - 20,
The markdown pseudo-code block containing the checklist lines starting with
"gitnexus_impact({target: "X", direction: "upstream"})" should include a
language specifier (e.g., ```text or ```plaintext) to satisfy markdownlint
MD040; update the fenced code block surrounding the four lines (the block with
gitnexus_impact, gitnexus_query, gitnexus_context and the Plan update order
line) to use a non-executable language specifier so the content is treated as
plain text.
.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md (1)

15-21: Consider adding language specifiers to fenced code blocks.

The markdownlint warnings about missing language specifiers (MD040) are valid but low priority. Since these blocks contain pseudo-code workflow descriptions rather than executable code, you could use ```text or ```plaintext to silence the warnings while accurately describing the content type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md around lines 15 -
21, The fenced code block containing the pseudo-code workflow (lines showing
gitnexus_impact({target: "X", direction: "upstream"}), READ
gitnexus://repo/{name}/processes, gitnexus_detect_changes(), etc.) should
include a language specifier such as ```text or ```plaintext to silence MD040;
update the SKILL.md fenced block start to use one of these specifiers so the
block is still clearly non-executable pseudo-code while satisfying markdownlint.
gitnexus/test/unit/sync-skills.test.ts (1)

497-536: T7.2 (target directory read-only) test case is omitted.

The test plan in docs/skill-sync.md lists T7.2 for testing read-only target directory errors. This test is absent from the implementation. Since planSync is a pure function that doesn't perform writes (that's the CLI script's responsibility), this is acceptable—but consider adding a note or updating the test plan to reflect that T7.2 is not applicable to planSync.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus/test/unit/sync-skills.test.ts` around lines 497 - 536, The test
suite documents a T7.2 case (target directory read-only) but the test is missing
because planSync is a pure function and doesn't perform writes; update the test
plan or tests to reflect this by either (a) adding a short skipped test labeled
"T7.2 — Target directory read-only (not applicable to planSync)" in the 'T7 —
Error Handling' describe block that calls planSync and immediately skips/asserts
not applicable, or (b) edit the documentation (docs/skill-sync.md) to mark T7.2
as CLI-only and not applicable to planSync; reference the test suite name 'T7 —
Error Handling', the test identifier T7.2, and the planSync function when making
the change so readers know why the test is omitted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/gitnexus/gitnexus-debugging/SKILL.md:
- Around line 15-20: The markdown generator is emitting unlabeled fenced code
blocks (examples show backtick blocks containing gitnexus_query,
gitnexus_context, READ gitnexus://repo/... and gitnexus_cypher) which triggers
MD040; update the canonical skill source or the sync/export step that renders
SKILL.md so that every fenced block includes an explicit language hint (e.g.,
```text for plain examples, ```bash for shell snippets, ```cypher for cypher
queries) rather than unlabeled ```; ensure the change affects all similar blocks
(the ones containing gitnexus_query, gitnexus_context, READ gitnexus://repo/...
and gitnexus_cypher) so the generated file no longer contains unlabeled fences.

In `@CLAUDE.md`:
- Around line 59-62: The resource URLs in CLAUDE.md (the entries containing
`gitnexus://repo/sync_skills_across_integration/context`, `.../clusters`,
`.../processes`, and `.../process/{name}`) were changed to reference the
branch-based index name; ensure these URLs are consistent with the index name
change by either reverting them back to the previous index naming scheme or
updating them to use the new branch-based index across all four entries, and if
you later revert the index name change make the inverse update to these same URL
strings so they stay synchronized.
- Line 4: The documentation currently uses the branch-derived index name
"sync_skills_across_integration" instead of the canonical "GitNexus"; update
CLAUDE.md and AGENTS.md to revert or replace every occurrence of
"sync_skills_across_integration" with "GitNexus" (check the three occurrences in
CLAUDE.md and the ones in AGENTS.md) so the main-branch docs use the correct
index name and semantics.

In `@docs/skill-sync.md`:
- Around line 118-119: Summary: The doc uses inconsistent capitalization for
"Markdown" in the sentence about `.claude` copies; please standardize it. Locate
the sentence referencing ".claude copies" (the line: "The `.claude` copies have
prettified markdown tables with column padding...") and change "markdown" to
"Markdown" to match proper capitalization and project style for the term.
- Around line 65-66: Update the documentation text to capitalize the word
"Markdown" where it appears in the listed items (specifically replace
occurrences of "markdown" in the strings "`.claude` copies have prettified
markdown table columns" and "compact table formatting" context if applicable) so
the formatting language is treated as a proper noun; search for the literal
"markdown" in the docs/skill-sync.md content and change it to "Markdown" to
satisfy static analysis.

In `@gitnexus-cursor-integration/skills/gitnexus-guide/SKILL.md`:
- Around line 30-39: Update the tool reference table so the invocation names
match the rest of the docs by replacing the bare tool names with their prefixed
forms: change query → gitnexus_query, context → gitnexus_context, impact →
gitnexus_impact, detect_changes → gitnexus_detect_changes, rename →
gitnexus_rename, cypher → gitnexus_cypher, and list_repos → gitnexus_list_repos
(if that command is exposed) so callers can copy the examples safely; ensure the
same exact prefixed identifiers are used for each corresponding row in the
table.

In `@gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md`:
- Around line 71-76: The fenced code block containing gitnexus_impact({target:
"validateUser", direction: "upstream"}) is unlabeled and triggers markdownlint
MD040; update the source generator or sync transform that emits this block so it
includes a language tag (e.g., change the fence to ```text) rather than editing
the derived SKILL.md directly; ensure the transform that outputs the
gitnexus_impact block (or the routine that formats impact blocks) always emits a
labeled fence.

In `@gitnexus/scripts/sync-skills.ts`:
- Around line 26-27: The script uses import.meta.dirname to compute REPO_ROOT
(and SOURCE_DIR) which requires Node.js 20.11+, so replace that usage with the
Node 18-compatible pattern: derive the current file path from
fileURLToPath(import.meta.url) and then use path.dirname to get the directory,
then compute REPO_ROOT and SOURCE_DIR from that; update references to REPO_ROOT
and SOURCE_DIR accordingly in sync-skills.ts (or alternatively bump the
package.json engines to "node": ">=20.11.0" if you want to require the newer
runtime).

---

Outside diff comments:
In `@gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md`:
- Around line 15-20: The markdown code fences in SKILL.md are missing explicit
languages (markdownlint MD040); update the generated source (the canonical skill
or the sync transform that produces SKILL.md) to emit fenced blocks with a
language token (e.g., ```text) for the example lists that reference
gitnexus_query, gitnexus_context, READ gitnexus://..., and gitnexus_cypher so
all occurrences (the blocks around lines shown and the other untyped blocks at
26-34, 50-54, 58-63, 74-86) are rendered as ```text ... ``` instead of bare ```
... ```, ensuring the generator/template that builds SKILL.md emits the language
token rather than editing only this output file.

In `@gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md`:
- Around line 15-21: The markdown contains multiple unlabeled fenced code blocks
(e.g., the block starting with "1. READ gitnexus://repos → Discover indexed
repos" and the block starting with 'gitnexus_query({query: "payment
processing"})'), which triggers MD040; update each bare triple-backtick fence in
SKILL.md to include a language tag (use "text") so they become ```text ... ```;
ensure you apply the same change to every other unlabeled fence in the file
(including the other examples referenced) so all fenced blocks are
language-tagged consistently.

In `@gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md`:
- Around line 16-21: The markdown has multiple code fences missing language tags
(e.g., the examples containing gitnexus_impact, READ
gitnexus://repo/{name}/processes, gitnexus_detect_changes, and the
gitnexus_detect_changes({scope: "staged"}) output block), causing MD040
violations; update the canonical generator/template so these specific fenced
blocks are emitted with an explicit language (use "text" for plain examples) and
apply the same fix to all other untyped fences referenced (lines corresponding
to the other example blocks), ensuring each fence around the example sequences
includes a language tag like ```text rather than leaving it untyped.

---

Nitpick comments:
In @.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md:
- Around line 15-21: The fenced code block containing the pseudo-code workflow
(lines showing gitnexus_impact({target: "X", direction: "upstream"}), READ
gitnexus://repo/{name}/processes, gitnexus_detect_changes(), etc.) should
include a language specifier such as ```text or ```plaintext to silence MD040;
update the SKILL.md fenced block start to use one of these specifiers so the
block is still clearly non-executable pseudo-code while satisfying markdownlint.

In @.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md:
- Around line 15-20: The markdown pseudo-code block containing the checklist
lines starting with "gitnexus_impact({target: "X", direction: "upstream"})"
should include a language specifier (e.g., ```text or ```plaintext) to satisfy
markdownlint MD040; update the fenced code block surrounding the four lines (the
block with gitnexus_impact, gitnexus_query, gitnexus_context and the Plan update
order line) to use a non-executable language specifier so the content is treated
as plain text.

In `@gitnexus/test/unit/sync-skills.test.ts`:
- Around line 497-536: The test suite documents a T7.2 case (target directory
read-only) but the test is missing because planSync is a pure function and
doesn't perform writes; update the test plan or tests to reflect this by either
(a) adding a short skipped test labeled "T7.2 — Target directory read-only (not
applicable to planSync)" in the 'T7 — Error Handling' describe block that calls
planSync and immediately skips/asserts not applicable, or (b) edit the
documentation (docs/skill-sync.md) to mark T7.2 as CLI-only and not applicable
to planSync; reference the test suite name 'T7 — Error Handling', the test
identifier T7.2, and the planSync function when making the change so readers
know why the test is omitted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e52e90c6-4218-41cc-93a2-e0634ce213e8

📥 Commits

Reviewing files that changed from the base of the PR and between 1952c2c and ddff5f8.

📒 Files selected for processing (33)
  • .claude/skills/gitnexus/gitnexus-cli/SKILL.md
  • .claude/skills/gitnexus/gitnexus-debugging/SKILL.md
  • .claude/skills/gitnexus/gitnexus-exploring/SKILL.md
  • .claude/skills/gitnexus/gitnexus-guide/SKILL.md
  • .claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md
  • .claude/skills/gitnexus/gitnexus-pr-review/SKILL.md
  • .claude/skills/gitnexus/gitnexus-refactoring/SKILL.md
  • .claude/skills/gitnexus/skills.manifest.json
  • .github/workflows/ci.yml
  • AGENTS.md
  • CLAUDE.md
  • docs/skill-sync.md
  • gitnexus-claude-plugin/skills/gitnexus-cli/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-guide/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-impact-analysis/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-pr-review/SKILL.md
  • gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md
  • gitnexus-claude-plugin/skills/skills.manifest.json
  • gitnexus-cursor-integration/skills/gitnexus-cli/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-guide/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-pr-review/SKILL.md
  • gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md
  • gitnexus-cursor-integration/skills/skills.manifest.json
  • gitnexus/package.json
  • gitnexus/scripts/sync-skills.ts
  • gitnexus/src/cli/setup.ts
  • gitnexus/src/sync-skills.ts
  • gitnexus/test/unit/sync-skills.test.ts

Comment on lines +15 to +20
```
1. gitnexus_query({query: "<error or symptom>"}) → Find related execution flows
2. gitnexus_context({name: "<suspect>"}) → See callers/callees/processes
3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow
4. gitnexus_cypher({query: "MATCH path..."}) → Custom traces if needed
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add explicit fence languages in the generated markdown.

These unlabeled fenced blocks trigger markdownlint MD040 repeatedly. Since this file is auto-generated, please fix the canonical skill source or sync step to emit languages like text, bash, or cypher instead of patching the derived file directly.

Also applies to: 26-34, 50-54, 58-63, 74-86

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/gitnexus/gitnexus-debugging/SKILL.md around lines 15 - 20,
The markdown generator is emitting unlabeled fenced code blocks (examples show
backtick blocks containing gitnexus_query, gitnexus_context, READ
gitnexus://repo/... and gitnexus_cypher) which triggers MD040; update the
canonical skill source or the sync/export step that renders SKILL.md so that
every fenced block includes an explicit language hint (e.g., ```text for plain
examples, ```bash for shell snippets, ```cypher for cypher queries) rather than
unlabeled ```; ensure the change affects all similar blocks (the ones containing
gitnexus_query, gitnexus_context, READ gitnexus://repo/... and gitnexus_cypher)
so the generated file no longer contains unlabeled fences.

Comment thread CLAUDE.md
# GitNexus — Code Intelligence

This project is indexed by GitNexus as **GitNexus** (1573 symbols, 4146 relationships, 120 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
This project is indexed by GitNexus as **sync_skills_across_integration** (1618 symbols, 4272 relationships, 123 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check what the index name should be based on repository configuration
# Look for other references to the index name pattern
rg -n "sync_skills_across_integration" --type md

Repository: L1nusB/GitNexus

Length of output: 1702


🏁 Script executed:

#!/bin/bash
# Check if there are any other index names referenced in the codebase
# to understand the naming convention
rg -n "GitNexus as \*\*" --type md -A 1

# Also check the git history for this file to see what the previous index name was
git log --oneline -n 5 CLAUDE.md 2>/dev/null || echo "Git history not available"

# Look for any configuration or environment files that might define the index name
fd -t f \( -name "*.env*" -o -name "*.config*" -o -name "README*" \) | head -20

Repository: L1nusB/GitNexus

Length of output: 856


🏁 Script executed:

#!/bin/bash
# Check the previous version of CLAUDE.md to see what the index name was before
git show HEAD~1:CLAUDE.md 2>/dev/null | head -20

# Also look at the README to understand the project setup
cat README.md 2>/dev/null | head -50

# Search for any references to index naming or GitNexus setup
rg "indexed by GitNexus" --type md -B 2 -A 2

Repository: L1nusB/GitNexus

Length of output: 3594


🏁 Script executed:

#!/bin/bash
# Get the git diff to see what changed in CLAUDE.md
git diff HEAD~1 CLAUDE.md 2>/dev/null || echo "Diff not available"

# Search for any other potential index names that might have been used before
rg "indexed by GitNexus as \*\*" --type md -A 1

# Check if there are any tags or versions that might indicate naming pattern
git tag --list 2>/dev/null | head -10 || echo "No tags"

# Look at git log for CLAUDE.md with more detail
git log --oneline --all -- CLAUDE.md 2>/dev/null | head -10

Repository: L1nusB/GitNexus

Length of output: 1300


🏁 Script executed:

#!/bin/bash
# Check the specific commit to see what changed
git show ddff5f8:CLAUDE.md 2>/dev/null | head -20 | grep -A 2 "indexed by"

# Look further back to see the original index name
git show 0796e1e:CLAUDE.md 2>/dev/null | head -20 | grep -A 2 "indexed by"

# Check main branch to see what index name it uses
git show main:CLAUDE.md 2>/dev/null | head -20 | grep -A 2 "indexed by" || echo "main branch not available or file not there"

# Show the full diff from a few commits ago
git diff 0796e1e CLAUDE.md 2>/dev/null | head -50

Repository: L1nusB/GitNexus

Length of output: 3148


Revert index name from branch name before merging to main.

The index name was changed from GitNexus to sync_skills_across_integration across CLAUDE.md (lines 4, 20, 59–62) and AGENTS.md. Using the branch name as the index breaks documentation semantics on the main branch. Either revert this to GitNexus or update the documentation to reflect the correct index name before merging.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 4, The documentation currently uses the branch-derived
index name "sync_skills_across_integration" instead of the canonical "GitNexus";
update CLAUDE.md and AGENTS.md to revert or replace every occurrence of
"sync_skills_across_integration" with "GitNexus" (check the three occurrences in
CLAUDE.md and the ones in AGENTS.md) so the main-branch docs use the correct
index name and semantics.

Comment thread CLAUDE.md
Comment on lines +59 to +62
| `gitnexus://repo/sync_skills_across_integration/context` | Codebase overview, check index freshness |
| `gitnexus://repo/sync_skills_across_integration/clusters` | All functional areas |
| `gitnexus://repo/sync_skills_across_integration/processes` | All execution flows |
| `gitnexus://repo/sync_skills_across_integration/process/{name}` | Step-by-step execution trace |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Resource URLs also updated to use branch name.

These resource URLs are consistent with the index name change on line 4. If the index name change is reverted, these URLs should also be updated accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 59 - 62, The resource URLs in CLAUDE.md (the entries
containing `gitnexus://repo/sync_skills_across_integration/context`,
`.../clusters`, `.../processes`, and `.../process/{name}`) were changed to
reference the branch-based index name; ensure these URLs are consistent with the
index name change by either reverting them back to the previous index naming
scheme or updating them to use the new branch-based index across all four
entries, and if you later revert the index name change make the inverse update
to these same URL strings so they stay synchronized.

Comment thread docs/skill-sync.md Outdated
Comment thread docs/skill-sync.md Outdated
Comment on lines +30 to +39
| Tool | What it gives you |
| ---------------- | ------------------------------------------------------------------------ |
| `query` | Process-grouped code intelligence — execution flows related to a concept |
| `context` | 360-degree symbol view — categorized refs, processes it participates in |
| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
| `detect_changes` | Git-diff impact — what do your current changes affect |
| `rename` | Multi-file coordinated rename with confidence-tagged edits |
| `cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
| `list_repos` | Discover indexed repos |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align the reference table with the invocation names used everywhere else.

The sibling skill docs in this same target tell users to call gitnexus_query, gitnexus_context, gitnexus_impact, etc., but this table advertises the bare names instead. That makes the guide unsafe to copy from unless the canonical source is updated to match the rest of the synced docs.

Suggested fix
-| `query`          | Process-grouped code intelligence — execution flows related to a concept |
-| `context`        | 360-degree symbol view — categorized refs, processes it participates in  |
-| `impact`         | Symbol blast radius — what breaks at depth 1/2/3 with confidence         |
-| `detect_changes` | Git-diff impact — what do your current changes affect                    |
-| `rename`         | Multi-file coordinated rename with confidence-tagged edits               |
-| `cypher`         | Raw graph queries (read `gitnexus://repo/{name}/schema` first)           |
+| `gitnexus_query`          | Process-grouped code intelligence — execution flows related to a concept |
+| `gitnexus_context`        | 360-degree symbol view — categorized refs, processes it participates in  |
+| `gitnexus_impact`         | Symbol blast radius — what breaks at depth 1/2/3 with confidence         |
+| `gitnexus_detect_changes` | Git-diff impact — what do your current changes affect                    |
+| `gitnexus_rename`         | Multi-file coordinated rename with confidence-tagged edits               |
+| `gitnexus_cypher`         | Raw graph queries (read `gitnexus://repo/{name}/schema` first)           |

If list_repos is also exposed with a gitnexus_ prefix in this target, it should be updated here too for consistency.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Tool | What it gives you |
| ---------------- | ------------------------------------------------------------------------ |
| `query` | Process-grouped code intelligence — execution flows related to a concept |
| `context` | 360-degree symbol view — categorized refs, processes it participates in |
| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
| `detect_changes` | Git-diff impact — what do your current changes affect |
| `rename` | Multi-file coordinated rename with confidence-tagged edits |
| `cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
| `list_repos` | Discover indexed repos |
| Tool | What it gives you |
| ---------------- | ------------------------------------------------------------------------ |
| `gitnexus_query` | Process-grouped code intelligence — execution flows related to a concept |
| `gitnexus_context` | 360-degree symbol view — categorized refs, processes it participates in |
| `gitnexus_impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
| `gitnexus_detect_changes` | Git-diff impact — what do your current changes affect |
| `gitnexus_rename` | Multi-file coordinated rename with confidence-tagged edits |
| `gitnexus_cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
| `list_repos` | Discover indexed repos |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus-cursor-integration/skills/gitnexus-guide/SKILL.md` around lines 30 -
39, Update the tool reference table so the invocation names match the rest of
the docs by replacing the bare tool names with their prefixed forms: change
query → gitnexus_query, context → gitnexus_context, impact → gitnexus_impact,
detect_changes → gitnexus_detect_changes, rename → gitnexus_rename, cypher →
gitnexus_cypher, and list_repos → gitnexus_list_repos (if that command is
exposed) so callers can copy the examples safely; ensure the same exact prefixed
identifiers are used for each corresponding row in the table.

Comment on lines +71 to 76

```
gitnexus_impact({target: "validateUser", direction: "upstream"})
→ d=1: loginHandler, apiMiddleware, testUtils
→ Affected Processes: LoginFlow, TokenRefresh
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language tag to this fenced block at the source.

This block still trips markdownlint MD040 because the fence is unlabeled. Since this file is auto-generated, please fix the canonical skill doc or the sync transform rather than editing the derived file directly.

Suggested fix
-```
+```text
 gitnexus_impact({target: "validateUser", direction: "upstream"})
 → d=1: loginHandler, apiMiddleware, testUtils
 → Affected Processes: LoginFlow, TokenRefresh
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>

[warning] 72-72: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md around
lines 71 - 76, The fenced code block containing gitnexus_impact({target:
"validateUser", direction: "upstream"}) is unlabeled and triggers markdownlint
MD040; update the source generator or sync transform that emits this block so it
includes a language tag (e.g., change the fence to ```text) rather than editing
the derived SKILL.md directly; ensure the transform that outputs the
gitnexus_impact block (or the routine that formats impact blocks) always emits a
labeled fence.


</details>

<!-- fingerprinting:phantom:triton:grasshopper -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment thread gitnexus/scripts/sync-skills.ts Outdated
…kdown capitalization

- Add `text` language tags to all unlabeled fenced code blocks in 5
  canonical skill sources (MD040)
- Replace import.meta.dirname with fileURLToPath + path.dirname in
  sync-skills.ts for Node 18 compatibility
- Capitalize 'Markdown' in docs/skill-sync.md

Amp-Thread-ID: https://ampcode.com/threads/T-019cc9a9-c4c3-7287-9802-f80a2eea305e

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
gitnexus/scripts/sync-skills.ts (1)

70-74: Consider validating that skills array contains only strings.

The validation confirms skills is an array but doesn't verify each element is a string. Malformed manifests with non-string entries would pass validation here but may cause issues downstream.

♻️ Optional enhancement
   if (!Array.isArray(parsed.skills)) {
     throw new Error(`Manifest at "${manifestPath}" is missing a "skills" array`);
   }
+
+  const invalidEntries = parsed.skills.filter((s: unknown) => typeof s !== 'string');
+  if (invalidEntries.length > 0) {
+    throw new Error(`Manifest at "${manifestPath}" contains non-string skills entries`);
+  }

   return parsed as Manifest;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gitnexus/scripts/sync-skills.ts` around lines 70 - 74, The manifest
validation currently only checks Array.isArray(parsed.skills); update it to
ensure every item is a string by iterating parsed.skills (e.g., using
Array.prototype.every) and throw a descriptive Error including manifestPath and
the bad index/value if any non-string is found; adjust the return cast to
Manifest only after this stricter check so downstream code using parsed.skills
as string[] is safe.
docs/skill-sync.md (1)

175-182: Consider adding a language specifier to the code block.

Static analysis flagged that fenced code blocks should have a language specified. Since this is an ASCII architecture diagram, consider using text or plaintext.

-```
+```text
 gitnexus/skills/*.md                 ← Single source of truth
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/skill-sync.md` around lines 175 - 182, The fenced ASCII diagram block
needs a language specifier to satisfy static analysis: update the code fence
that contains the diagram starting with "gitnexus/skills/*.md                 ←
Single source of truth" to use a plain text language tag (e.g., ```text or
```plaintext) so the block is recognized as text/plain; keep the existing
diagram content intact and only change the opening fence to include the
language.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/skill-sync.md`:
- Around line 175-182: The fenced ASCII diagram block needs a language specifier
to satisfy static analysis: update the code fence that contains the diagram
starting with "gitnexus/skills/*.md                 ← Single source of truth" to
use a plain text language tag (e.g., ```text or ```plaintext) so the block is
recognized as text/plain; keep the existing diagram content intact and only
change the opening fence to include the language.

In `@gitnexus/scripts/sync-skills.ts`:
- Around line 70-74: The manifest validation currently only checks
Array.isArray(parsed.skills); update it to ensure every item is a string by
iterating parsed.skills (e.g., using Array.prototype.every) and throw a
descriptive Error including manifestPath and the bad index/value if any
non-string is found; adjust the return cast to Manifest only after this stricter
check so downstream code using parsed.skills as string[] is safe.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6002ee49-26b5-4a92-be53-ad8bec962ce5

📥 Commits

Reviewing files that changed from the base of the PR and between ddff5f8 and 25d9c30.

📒 Files selected for processing (7)
  • docs/skill-sync.md
  • gitnexus/scripts/sync-skills.ts
  • gitnexus/skills/gitnexus-debugging.md
  • gitnexus/skills/gitnexus-exploring.md
  • gitnexus/skills/gitnexus-impact-analysis.md
  • gitnexus/skills/gitnexus-pr-review.md
  • gitnexus/skills/gitnexus-refactoring.md
✅ Files skipped from review due to trivial changes (3)
  • gitnexus/skills/gitnexus-refactoring.md
  • gitnexus/skills/gitnexus-exploring.md
  • gitnexus/skills/gitnexus-impact-analysis.md

@L1nusB L1nusB closed this Mar 7, 2026
L1nusB pushed a commit that referenced this pull request Mar 30, 2026
fixed prop cutoff issue for pr/issue filtering
L1nusB pushed a commit that referenced this pull request Mar 30, 2026
…gyanpatwari#498)

* feat: add COBOL language support with regex extraction pipeline

Standalone COBOL processor following the markdown-processor.ts pattern:
- No LanguageProvider modification — COBOL uses regex, not tree-sitter
- No SupportedLanguages enum change — standalone processor pattern

New files:
- cobol-processor.ts — orchestrator (processCobol, isCobolFile, isJclFile)
- cobol/cobol-preprocessor.ts — regex state machine extraction (~888 LOC)
- cobol/cobol-copy-expander.ts — COPY statement expansion with circular detection
- cobol/jcl-parser.ts — JCL job/step/DD extraction
- cobol/jcl-processor.ts — JCL graph node creation

Extraction produces:
- Module nodes (PROGRAM-ID)
- Function nodes (paragraphs)
- Namespace nodes (sections)
- Property nodes (data items)
- CALLS edges (PERFORM intra-file, CALL cross-program)
- IMPORTS edges (COPY statements)
- CONTAINS edges (section → paragraph hierarchy)

Pipeline integration: single processCobol() call in Phase 2.6

54 new tests (33 COBOL + 21 JCL), all 3889 tests pass.

* docs: document custom processor pattern in pipeline.ts

Add comment block at the custom processor integration point
documenting the pattern for future non-tree-sitter language additions.

* feat(cobol): enrich graph with EXEC SQL/CICS, ENTRY points, MOVE data flow, PERFORM THRU

Maps the remaining 60% of CobolRegexResults to the graph:
- EXEC SQL blocks → CodeElement nodes + ACCESSES edges to DB tables
- EXEC CICS LINK/XCTL → CodeElement nodes + cross-program CALLS edges
- ENTRY points → Constructor nodes (registered for cross-program resolution)
- MOVE statements → ACCESSES edges (read/write data flow tracking)
- PERFORM THRU → expanded CALLS edges for range targets
- File declarations → Record nodes with assignment metadata
- Cross-program CALL 2nd pass: resolves unresolved targets after all programs processed

* test(cobol): add 26 integration tests with exact assertions + fix CICS resolution bug

Integration tests (test/integration/resolvers/cobol.test.ts):
- 26 tests covering full COBOL system extraction
- ALL assertions use exact toBe(N) — zero fuzzy assertions
- Fixtures: CUSTUPDT.cbl, AUDITLOG.cbl, CUSTDAT.cpy, RPTGEN.cbl, RUNJOBS.jcl

Bug fix (cobol-processor.ts):
- CICS LINK/XCTL cross-program resolution was broken — edges were
  created with "resolved" reason but pointing to <unresolved> targets
- Fix: use cics-link-unresolved / cics-xctl-unresolved suffix pattern
  matching the existing cobol-call-unresolved pattern
- Second-pass resolver now patches both CALL and CICS unresolved edges

All 3915 tests pass, 0 failures.

* test(cobol): exhaustive 57-test suite with strict exact assertions

Complete rewrite of COBOL integration tests using ground-truth approach:
dump the full graph, then assert EVERY node and EVERY edge.

57 tests across 9 sections:
- Node completeness: Module(3), Function(13), Namespace(2), Property(21),
  Record(1), CodeElement(8), Constructor(1) — exact sorted arrays
- Edge completeness: 22 tests covering every type+reason combination
  with exact source→target pairs
- Cross-program resolution: 6 tests verifying CALL, CICS LINK/XCTL, JCL
- COPY expansion: copybook data items in RPTGEN
- Section hierarchy: exact paragraph membership per section
- Data item ownership: exact per-module breakdown
- MOVE data flow: exact read/write pairs
- JCL integration: job/step/dataset containment
- Grand totals: CALLS(22), CONTAINS(48), IMPORTS(1), ACCESSES(7)

Fixture enhancements:
- CUSTUPDT.cbl: added INIT-SECTION + PROCESSING-SECTION, PERFORM THRU
- AUDITLOG.cbl: added ENTRY "AUDITLOG-BATCH"
- RPTGEN.cbl: added EXEC CICS XCTL

Zero fuzzy assertions — every expect uses toBe(N) or toEqual([...sorted]).

* fix(cobol): add removeRelationship API + single-quote CALL/COPY/ENTRY, PERFORM keyword skip

Phase 0A: Add removeRelationship(id) to KnowledgeGraph interface and
implementation (trivial Map.delete wrapper). Required for orphan edge
cleanup in next commit.

Phase 1A (from PR abhigyanpatwari#500 review, modified):
- RE_CALL and RE_COPY_QUOTED now match both "double" and 'single' quotes
- parseSingleCopyStatement in copy-expander updated for single quotes
- PERFORM_KEYWORD_SKIP set prevents UNTIL/VARYING/WITH/TEST/FOREVER
  from being stored as false-positive perform targets
- Sequence number stripping uses /[^0-9 ]/ (preserves numeric seq numbers
  unlike PR abhigyanpatwari#500's /\S/ which stripped them)
- Normalized || to ?? for regex group extraction in copy-expander

5 new graph unit tests, all 57 COBOL integration tests pass.

* fix(cobol): RE_ENTRY single-quote + remove orphan unresolved CALLS edges

Phase 1B: RE_ENTRY regex now supports both "double" and 'single' quoted
ENTRY targets. Uses named intermediates (entryName, usingClause) with ??
operator. USING capture group shifted from [2] to [3].

Phase 1C: Second-pass resolution now collects resolved orphan edge IDs
during iteration and removes them after the loop completes, using the new
graph.removeRelationship() API. Graph no longer contains phantom
<unresolved>: edges alongside their resolved replacements. CALLS count
drops from 22 to 18 (4 orphan edges removed).

* fix(cobol): Property ID collisions + O(1) Map lookup for MOVE edges

Phase 1D+3C (atomic): Property node IDs now use composite key
filePath:section:level:name instead of filePath:name. This prevents
duplicate data item names in different sections (e.g., STATUS in both
WORKING-STORAGE and LINKAGE) from silently colliding.

New generatePropertyId() helper ensures both node creation and MOVE
edge lookup use the identical key formula. buildDataItemMap() replaces
the O(n) findDataItemNode linear scan with O(1) Map lookup, built once
per file before MOVE processing.

* feat(cobol): MOVE multi-target extraction with OF/IN qualifier filtering

MOVE X TO A B C now produces write edges for all targets, not just the
first. extractMoveTargets() helper handles OF/IN qualified names
(WS-NAME OF WS-RECORD -> target is WS-NAME), subscript stripping
(WS-TABLE(I) -> WS-TABLE), and MOVE_SKIP filtering on targets.

Data model: CobolRegexResults.moves.to:string -> targets:string[]
MOVE CORRESPONDING stays single-target per COBOL standard.
Processor MOVE loop now iterates move.targets.

* feat(cobol): COPY IN/OF library, pseudotext REPLACING, dynamic CALL, PERFORM TIMES, CICS MAP unquoted

Phase 2B: COPY ... IN/OF library-name now captured as metadata in
CopyResolution (IN and OF are synonyms per COBOL-85 standard).

Phase 2C: COPY REPLACING ==pseudotext== support. Tokenizer handles
==...== delimiters alongside "quoted" strings. Pseudotext forces EXACT
type. Two-pass applyReplacing: first pass handles space-containing/
non-identifier pseudotext via global string replace; second pass handles
identifier-level LEADING/TRAILING/EXACT. New test file
cobol-copy-expander.test.ts with 10 tests.

Phase 2E: PERFORM WS-COUNT TIMES no longer produces a false-positive
perform target (checks for TIMES keyword after captured identifier).

Phase 2F: Dynamic CALL via data item (CALL WS-PROG-NAME without quotes)
now emits a CodeElement annotation node with description 'dynamic-call'
instead of silently ignoring. Adds isQuoted:boolean to call results.

Phase 3A: CICS MAP(WS-MAP-NAME) unquoted identifiers now captured.
Phase 3B: Normalized || to ?? in copy-expander (done in Phase 1A).

* feat(cobol): nested program support — capture multiple PROGRAM-IDs per file

Phase 2D: The state machine now captures all PROGRAM-IDs, not just the
first. The primary program name stays in programName; additional nested
programs go into nestedPrograms[]. The processor creates separate Module
nodes for each nested program, contained by the outer module, and
registers them in moduleNodeIds for cross-program CALL resolution.

Paragraphs/data items are not yet scoped per-program (attributed to the
outer module) — full per-program scoping is a future enhancement that
requires END PROGRAM boundary tracking in the state machine.

* test(cobol): expand integration tests for all new language features

New fixtures:
- NESTED.cbl — two PROGRAM-IDs (OUTER-PROG, INNER-PROG) for nested
  program support testing
- COPYLIB.cpy — copybook for pseudotext REPLACING test target

Modified fixtures:
- CUSTUPDT.cbl — single-quoted ENTRY 'ALTENTRY', multi-target MOVE
  (WS-AMT TO FIELD-A FIELD-B), dynamic CALL WS-PROG-NAME, COPY COPYLIB
  with pseudotext REPLACING, LINKAGE SECTION with LS-PARAM
- RPTGEN.cbl — PERFORM WS-COUNT TIMES (false-positive guard), unquoted
  MAP(WS-MAP-NAME), additional data items WS-COUNT WS-MAP-NAME

Integration test rewritten with 62 exact assertions covering:
- 5 Module, 17 Function, 33 Property, 9 CodeElement, 2 Constructor nodes
- Nested program containment (OUTER-PROG -> INNER-PROG)
- Dynamic CALL annotation (CodeElement with cobol-dynamic-call)
- Multi-target MOVE (UPDATE-BALANCE: 2 reads, 3 writes)
- Single-quoted ENTRY (ALTENTRY under CUSTUPDT)
- PERFORM TIMES guard (WS-COUNT not in CALLS)
- Orphan unresolved edge removal (zero -unresolved edges)
- Grand totals: 21 CALLS, 68 CONTAINS, 2 IMPORTS, 10 ACCESSES

* fix(cobol): pseudotext REPLACING now applies correctly via isPseudotext flag

Root cause: ==PREFIX-== matched /^[A-Z][A-Z0-9-]*$/i (trailing hyphens
allowed), routing it to the second-pass EXACT identifier match where
PREFIX-RECORD !== PREFIX- failed silently.

Fix: Propagate isPseudotext from parseReplacingClause to CopyReplacing
interface, then use it in applyReplacing first-pass condition to force
global string replacement for all pseudotext entries regardless of
whether the content looks like an identifier.

Result: COPY COPYLIB REPLACING ==PREFIX-== BY ==WS-==. now correctly
transforms PREFIX-RECORD → WS-RECORD, PREFIX-CODE → WS-CODE, etc.

* refactor(cobol): per-program scoping via boundary tracking + line-range grouping

State machine changes (minimal, ~30 lines):
- Add RE_END_PROGRAM regex for END PROGRAM program-name. detection
- Replace nestedPrograms[] with programs[] containing startLine/endLine/
  nestingDepth metadata for each PROGRAM-ID in the file
- Reset division/section/paragraph state on new PROGRAM-ID boundary
- EOF finalization flushes remaining stack entries (single-program files)
- Programs sorted by startLine (outer before inner)

Processor changes:
- Uses programs[] with line-range containment to find enclosing parent
  Module for nested programs (replaces hardcoded nestedParent logic)
- programModuleIds Map tracks Module node IDs per program name

Fixture: NESTED.cbl now includes END PROGRAM lines for both programs.

Integration test: PREFIX-* Property nodes now correctly appear as WS-*
after the pseudotext REPLACING fix from the previous commit.

* feat(cobol): free-format COBOL support (>>source free)

Auto-detects >>SOURCE FREE directive in the first 500 chars and switches
to free-format line processing:
- No column-position rules (cols 1-6 are program text, not sequence area)
- Comments use *> prefix instead of col 7 indicator
- No continuation line indicator
- Strip inline *> comments
- Skip >>SOURCE directive lines

preprocessCobolSource() skips col-1-6 stripping for free-format files.

Paragraph/section regexes relaxed from fixed 7-space prefix to flexible
whitespace with case-insensitivity (/^\s*([A-Z][A-Z0-9-]+)\.\s*$/i).
EXCLUDED_PARA_NAMES expanded with COBOL verbs (GOBACK, END-READ, etc.)
to prevent false-positive paragraph detection in free-format.

Also fixes: entry-point-scoring.ts crash when language is 'cobol'
(MERGED_ENTRY_POINT_PATTERNS[language] was undefined → optional chaining).

Benchmark on ACAS 3.01 (268 GnuCOBOL free-format programs, 10MB):
- Before: 407 nodes, 393 edges (near-empty, only file nodes)
- After:  4,297 nodes, 3,612 edges, 542 clusters, 11 flows

* fix(cobol): relax data item regexes for free-format (^\s+ to ^\s*)

RE_FD, RE_DATA_ITEM, RE_ANONYMOUS_REDEFINES, and RE_88_LEVEL all used
^\s+ which requires at least 1 leading space. In free-format mode, lines
are trimmed before processing, so data items like "01 WS-FIELD PIC X."
have no leading whitespace after trimming.

Changed to ^\s* (zero or more spaces) which works for both fixed-format
(indented lines still have spaces) and free-format (trimmed lines).

ACAS benchmark (268 GnuCOBOL programs):
- Before: 4,297 nodes, 3,612 edges (paragraphs only)
- After:  13,832 nodes, 8,615 edges (+ data items, FDs, 88-levels)

* feat(cobol): 100% structural feature coverage — GO TO, SCREEN, SD/RD, SORT, SEARCH, CANCEL, Level 66

New extractions: GO TO (CALLS edges), SCREEN SECTION data items,
SD/RD alongside FD (Record nodes), SORT/MERGE USING/GIVING (ACCESSES),
SEARCH (ACCESSES), CANCEL (CALLS), Level 66 RENAMES (Property),
IS EXTERNAL/IS GLOBAL (Property description enrichment).

ACAS: 13,951 nodes | 13,193 edges | 685 clusters | 150 flows
(+53% edges from new GO TO/SORT/SEARCH/CANCEL extractions)

* feat(cobol): enriched CICS extraction — file I/O, dynamic PROGRAM, queues, HANDLE ABEND

EXEC CICS blocks now extract:
- FILE/DATASET clause: captures VSAM file name (literal or data item ref)
  for READ/WRITE/REWRITE/DELETE/STARTBR/READNEXT/READPREV → ACCESSES edges
- PROGRAM clause: now handles unquoted variable references (dynamic CICS
  program transfer) → CodeElement annotation with cics-dynamic-program reason
- QUEUE clause: captures TS/TD queue names from WRITEQ/READQ → ACCESSES edges
- LABEL clause: captures HANDLE ABEND error handler targets → CALLS edges
- TRANSID: now handles unquoted variable references

CodeElement descriptions enriched with all captured fields (map, program,
transid, file, queue, label).

CardDemo benchmark: +49 nodes, +33 edges from enriched CICS extraction.

* feat(cobol): complete CICS command extraction — all 7 expert recommendations

From COBOL expert agent analysis:
1. ENDBR added to isRead file command list
2. LOAD added to PROGRAM edge commands (alongside LINK/XCTL)
3. Two-word commands expanded: WRITEQ/READQ/DELETEQ TS/TD, HANDLE
   ABEND/AID/CONDITION, START TRANSID
4. Queue reason differentiated: cics-queue-read/-write/-delete
5. RETURN/START TRANSID → CALLS edges to synthetic <transid> target
6. MAP → ACCESSES edges for screen traceability
7. INTO/FROM data fields extracted → ACCESSES edges to data items

Also: dataItemMap built before CICS block processing (was declared after),
CodeElement descriptions enriched with all captured CICS fields.

* test(cobol): strict exhaustive integration tests with exact edgeSet assertions

Every edge reason has exact sorted pair assertions via edgeSet(), not
just counts. Any change to extraction that adds, removes, or reorders
edges will produce a precise, descriptive failure.

Updated RPTGEN.cbl fixture with:
- GO TO EXIT-PARAGRAPH, SORT USING/GIVING, SEARCH table
- EXEC CICS READ FILE INTO, WRITEQ TS QUEUE FROM, SEND MAP FROM
- EXEC CICS HANDLE ABEND LABEL, RETURN TRANSID, XCTL PROGRAM(variable)
- ABEND-HANDLER and EXIT-PARAGRAPH paragraphs

46 tests covering 24 CALLS + 79 CONTAINS + 18 ACCESSES + 2 IMPORTS edges
across 15 distinct edge reason codes, all with exact sorted pair lists.

* fix(cobol): address 5 findings from second Claude review (compiler front-end perspective)

Finding #2: Numeric sequence numbers now stripped (changed /[^0-9 ]/ to
/\S/ in preprocessCobolSource). Lines like "000100 MAIN-PARAGRAPH." now
have cols 1-6 blanked so paragraph regex matches correctly.

Finding abhigyanpatwari#11: JCL in-stream PROC ordering fixed — pre-register all PROCs
into moduleNames before step processing. Steps that EXEC a PROC defined
later in the same file now get CALLS edges.

Finding #A: PROCEDURE DIVISION USING no longer captures calling-convention
keywords (BY, VALUE, REFERENCE, CONTENT, ADDRESS, OF) as parameter names.

Finding #C: SORT/MERGE USING/GIVING now captures ALL file references
(multi-file), not just the first. Changed from single-match to section
extraction with split.

Finding #D: Section headers no longer set currentParagraph, preventing
PERFORM caller misattribution to Namespace instead of Function nodes.

* fix(cobol): address code review findings — ReDoS fix, perf, cleanup

P1 CRITICAL — ReDoS in SORT USING/GIVING:
Replaced nested-quantifier regex with safe indexOf+substring+split
approach. No backtracking possible on crafted input.

P2 — readCopy O(M) linear scan:
Added copybookByPath reverse Map for O(1) path-to-content lookup.

P3 — Dead code removal:
Deleted unused RE_SORT_USING and RE_SORT_GIVING constants.

P3 — EXCLUDED_PARA_NAMES simplification:
Replaced 20 END-* entries with startsWith('END-') prefix check.
Auto-covers future END-* verbs.

P3 — Misplaced JSDoc on removeRelationship:
Fixed comment that described removeNodesByFile instead.
Added missing JSDoc to removeNodesByFile.

Review agents: architecture-strategist, performance-oracle,
security-sentinel, code-simplicity-reviewer.

* refactor: add Cobol to SupportedLanguages with parseStrategy: standalone

New languages/cobol.ts — standalone regex processor provider with no-op
tree-sitter fields. Declares parseStrategy: 'standalone' to distinguish
from tree-sitter-based languages.

Added parseStrategy: 'tree-sitter' | 'standalone' to LanguageProviderConfig
for languages that use their own processor instead of tree-sitter.

Removed all 11 'cobol' as any casts — now uses SupportedLanguages.Cobol.
Added empty Cobol entries to entry-point-scoring and framework-detection.

* fix(cobol): 5 fixes from third Claude review + 3 regression tests

Fixes:
- Line numbers now 1-indexed in fixed-format (was 0-indexed, off-by-one
  in jump-to-definition links)
- Copybook content preprocessed before COPY expansion (sequence numbers
  and patch markers in copybooks no longer survive into expanded source)
- ENTRY USING filters calling-convention keywords (BY, VALUE, REFERENCE,
  CONTENT, ADDRESS, OF) — same fix as PROCEDURE DIVISION USING
- SORT/MERGE trailing period stripped from USING/GIVING file tokens
- Paragraph exclusion uses exact match for SECTION/DIVISION (was substring
  match that excluded valid names like CROSS-SECTION-ANALYSIS)

USING_KEYWORDS moved to module scope for reuse by both PROCEDURE DIVISION
USING and ENTRY USING handlers.

New unit tests:
- ENTRY USING BY VALUE filtering
- Paragraph names containing SECTION not excluded
- Numeric sequence numbers stripped enabling paragraph detection

* fix(cobol): address 6 findings from fourth Claude review + tests

Fourth review findings fixed:
- New #IV: PERFORM TIMES guard uses perfMatch.index instead of
  line.indexOf (prevents wrong match when target appears earlier in line)
- New #V: 88-level condition values now handle single-quoted literals
  ('Y' no longer stored with embedded quotes)
- New #I: CANCEL edges use two-pass resolution like CALL (no longer
  silently dropped when target indexed after source)
- New #3: Multi-line SORT/MERGE accumulation — sortAccum state variable
  accumulates lines until period, then extracts USING/GIVING from full
  statement (95% of production SORT statements span multiple lines)
- New #II: PROCEDURE DIVISION USING on split lines — pendingProcUsing
  flag defers parameter capture to next line if USING not on same line
- New #6 (prior): EXCLUDED_PARA_NAMES exact match for SECTION/DIVISION

Updated fixture: RPTGEN.cbl SORT now uses multi-line format with GIVING
on separate line (period-terminated). New sort-giving integration test.
ACCESSES total: 18 → 19 (new sort-giving edge from multi-line capture).

* fix(cobol): address 4 findings from fifth Claude review

Finding #B (5 reviews old): Section/paragraph node IDs now include
enclosing program name to prevent collision when nested programs share
section/paragraph names. New findOwningProgramName() helper uses
programs[] line ranges to find the innermost enclosing program.

Finding #α: pendingProcUsing now reset in the if(procUsingMatch) branch
(was only set in else branch, could leak across nested programs).

Finding #β: RE_CALL_DYNAMIC uses negative lookbehind (?<![A-Z0-9-]) to
prevent false-positive on compound identifiers like WS-CALL OCCURS.

Finding #γ: sortAccum flushed at EOF (parallel to flushSelect and
pendingFdName EOF cleanup). Prevents silent loss of SORT USING/GIVING
relationships in truncated files.

* fix(cobol): address findings from reviews 5+6 with full test coverage

Review 5 fixes:
- #α: pendingProcUsing reset in if(procUsingMatch) branch
- #β: RE_CALL_DYNAMIC negative lookbehind prevents WS-CALL false positive
- #γ: sortAccum flushed at EOF for truncated files
- #B: Section/paragraph IDs include owning program name

Review 6 fixes:
- #P: sectionNodeIds/paraNodeIds maps use program-scoped keys
  (PROGNAME:NAME). New scopedParaLookup/scopedCallerLookup helpers.
  findContainingSection updated with programs parameter.
- #Q: RETURNING added to USING_KEYWORDS for COBOL 2002+
- #R: RE_PERFORM matches both THRU and THROUGH via alternation

New unit tests (6):
- PERFORM THROUGH captures thruTarget
- PROCEDURE DIVISION USING RETURNING filters keyword
- RE_CALL_DYNAMIC no false-match on WS-CALL compound identifier
- Multi-line SORT captures USING/GIVING from continuation lines
- PROCEDURE DIVISION USING on split line via pendingProcUsing
- Copybook preprocessing strips sequence numbers

* fix(cobol): address findings from seventh Claude review + 3 tests

Review 7 fixes:
- #i: findContainingSection only updates best when lookup succeeds
  (prevents undefined overwriting valid parent section)
- #ii: RE_PROC_SECTION handles segment numbers (SECTION 30.)
- #III: procedureUsing now stored per-program on boundary stack
  entries, propagated to programs[] output. Inner programs no longer
  overwrite outer program's parameters.
- #δ: Dynamic CANCEL (CANCEL variable) now creates CodeElement
  annotation node, matching dynamic CALL behavior. RE_CANCEL_DYNAMIC
  with negative lookbehind. cancels[] gains isQuoted field.
- #Q: RETURNING added to USING_KEYWORDS (already in prev commit)
- #R: PERFORM THROUGH already fixed (THRU|THROUGH alternation)

New unit tests:
- Nested programs carry per-program procedureUsing
- SECTION with segment number detected
- Dynamic CANCEL via data item captured with isQuoted=false

* feat(cobol): link PROCEDURE DIVISION USING to LINKAGE data items + close 4 findings

Finding abhigyanpatwari#10 FIXED: procedureUsing parameters now create ACCESSES edges
with reason 'cobol-procedure-using' from Module to matching LINKAGE
SECTION Property nodes. This exposes the program's parameter contract
in the graph (e.g., AUDITLOG → LS-CUST-ID, AUDITLOG → LS-AMOUNT).

Findings closed by expert agent consensus:
- #6 COPY IN library: WONTFIX — captured metadata, no universal
  library-to-directory mapping exists. Field costs nothing and is useful
  for library queries.
- abhigyanpatwari#14 SQL DELETE: WONTFIX — DB2 requires FROM; existing FROM pattern
  handles it. Bare DELETE would risk false positives.
- #E OCCURS DEPENDING ON: WONTFIX — runtime sizing concern, not
  structural. The static occurs count is sufficient for indexing.

All 39 findings from 7 Claude reviews now resolved or closed.

* fix(cobol): resolve 48 review findings across 9 review cycles

Ninth deep review resolved all remaining COBOL parser gaps identified
by 5 specialist agents (COBOL expert, architecture strategist,
TypeScript reviewer, security sentinel, code simplicity reviewer).

Fixes (P1 — critical):
- SELECT OPTIONAL now correctly skips OPTIONAL keyword (C1)
- RETURNING params excluded from PROCEDURE DIVISION USING list (C7)
- SORT GIVING no longer captures clause keywords as file names (C5)
- Extract flushSort() helper eliminating 40-line duplication (S2)
- Flush unclosed EXEC blocks at EOF matching SORT/SELECT pattern (S3)
- Guard undefined map key in jcl-processor moduleNames (S1)
- Add MAX_TOTAL_EXPANSIONS=500 to prevent exponential COPY breadth (S4)

Fixes (P2 — important):
- Quote-aware stripInlineComment for | and *> in string literals (C2+C3)
- Fixed-format literal continuation now handles quoted strings (C6)
- PROGRAM-ID detected regardless of division state for siblings (C9)

Fixes (P3 — cleanup):
- EXEC SQL INTO restricted to INSERT INTO to avoid FETCH false-pos (C8)
- Copy expander line numbers fixed from 0-based to 1-based (C11)
- Remove dead code: inInStreamProc, fileIsLiteral, expansionDepth (S7-S10)

Also fixes 8th-review findings: nested program CONTAINS attribution,
multi-PERFORM on same line, INPUT/OUTPUT PROCEDURE IS in SORT,
GO TO DEPENDING ON multi-target, MOVE CORR abbreviation, per-program
procedureUsing ACCESSES edges.

Tests: 145 COBOL tests passing (59 integration + 86 unit)
Benchmarks: CardDemo 12,323 nodes/8,893 edges (7.4s)
            ACAS 14,016 nodes/15,452 edges (9.3s, -9% faster)

* docs(cobol): update documentation for ninth review cycle fixes

Update all 4 COBOL documentation files to reflect the 16 fixes
from the ninth review cycle:

- regex-extraction.md: quote-aware comment stripping, SELECT OPTIONAL,
  RETURNING exclusion, SORT_CLAUSE_NOISE filter, flushSort() helper,
  GO TO multi-target, PROGRAM-ID division-independent detection
- copy-expansion.md: MAX_TOTAL_EXPANSIONS=500 breadth guard, 1-based
  line numbers, removed expansionDepth/warnedCircular param
- deep-indexing.md: GO TO DEPENDING ON, INPUT/OUTPUT PROCEDURE IS,
  MOVE CORR edge reasons, INSERT INTO restriction, literal continuation
- performance.md: updated benchmarks (CardDemo 12,323n/8,893e/7.4s,
  ACAS 14,016n/15,452e/9.3s), COPY breadth guard

* fix(cobol): resolve 10th review findings — nested program edge attribution

Fix 6 findings from the 10th review (PR abhigyanpatwari#498 comment #4132201110):

#A+#F: All CALL/CANCEL/CICS/ENTRY/SQL/SEARCH/file-declaration edges
now use owningModuleId() for nested program attribution instead of
the outer program's parentId. Added helper function owningModuleId()
to centralize the pattern.

#B: Added USING and GIVING to SORT_CLAUSE_NOISE set to prevent MERGE
USING + OUTPUT PROCEDURE from capturing clause keywords as file names.

#C: INPUT/OUTPUT PROCEDURE regex now captures optional THRU/THROUGH
range end paragraph, mirroring RE_PERFORM's THRU support.

#D: scopedCallerLookup fallback now uses programModuleIds.get(pgm)
instead of parentId, so PERFORM/MOVE/GOTO in nested programs with
unresolvable paragraphs fall back to the correct inner module.

#E: pendingProcUsing only set when PROCEDURE DIVISION line is NOT
period-terminated, preventing false USING expectation.

Tests: 145 passing | TypeScript clean

* fix(cobol): resolve 10th review findings — nested program edge attribution

Fix 6 findings from the 10th review (PR abhigyanpatwari#498 comment #4132201110):

#A+#F: All CALL/CANCEL/CICS/ENTRY/SQL/SEARCH/file-declaration edges
now use owningModuleId() for nested program attribution instead of
the outer program's parentId. Added helper function owningModuleId()
to centralize the pattern.

#B: Added USING and GIVING to SORT_CLAUSE_NOISE set to prevent MERGE
USING + OUTPUT PROCEDURE from capturing clause keywords as file names.

#C: INPUT/OUTPUT PROCEDURE regex now captures optional THRU/THROUGH
range end paragraph, mirroring RE_PERFORM's THRU support.

#D: scopedCallerLookup fallback now uses programModuleIds.get(pgm)
instead of parentId, so PERFORM/MOVE/GOTO in nested programs with
unresolvable paragraphs fall back to the correct inner module.

#E: pendingProcUsing only set when PROCEDURE DIVISION line is NOT
period-terminated, preventing false USING expectation.

Tests: 145 passing | TypeScript clean

* fix(cobol): resolve 11th review findings — final nested program + multi-CALL gaps

#1: scopedCallerLookup(null) now uses owningModuleId(lineNum) instead
of parentId, fixing PERFORM/MOVE/GOTO before first paragraph in nested
programs.

#2+#3: CALL and CANCEL extraction now uses matchAll (global flag) to
capture multiple occurrences on the same line. Dynamic CALL/CANCEL
checked independently instead of in else branch.

#4: SORT/MERGE ACCESSES edge IDs now use owningModuleId(sort.line)
instead of parentId for nested program correctness.

#5: preprocessCobolSource free-format detection now uses first 10 lines
(consistent with extractCobolSymbolsWithRegex threshold).

#6: EXCLUDED_PARA_NAMES expanded with DISPLAY, ACCEPT, WRITE, READ,
REWRITE, DELETE, OPEN, CLOSE, RETURN, RELEASE, SORT, MERGE to prevent
false-positive paragraph detection on isolated verbs.

Also removed unused GraphNode import from cobol-processor.ts.

Tests: 145 passing | TypeScript clean

* docs(cobol): deepened full language coverage plan with research findings

3 research agents analyzed Phase 1-2 features and graph value ranking.

Key findings: cobol-call-using is #1 edge type (9.2/10); multi-line
accumulation is dominant challenge; DECLARATIVES is lowest-risk Phase 2
item; SET TO TRUE covers 80-90% of SET usage.

* feat(cobol): implement Phase 1 — high-value data flow edges

4 new extraction features that create new ACCESSES and IMPORTS edges:

1.1: EXEC SQL INCLUDE -> IMPORTS edges with reason 'sql-include'
     Handles unquoted (SQLCA), quoted ('DBRMLIB.MEMBER'), and
     underscored (CUST_TBL_DCL) member names.

1.2: CALL USING parameter extraction -> ACCESSES edges
     Extracts parameters from CALL USING clause, filtering BY/REFERENCE/
     CONTENT/VALUE/ADDRESS/OF/LENGTH/OMITTED keywords. Creates
     'cobol-call-using' ACCESSES edges (graph value: 9.2/10).

1.4: OCCURS DEPENDING ON -> ACCESSES edges with reason 'cobol-depends-on'
     Extended OCCURS regex captures DEPENDING ON field with subscript
     stripping. Creates dependency edge from table to controlling field.

1.5: VALUE clause for standard data items
     Extracts VALUE from data item clauses: quoted strings with type
     prefix (X/N/G/B), ALL literals, numerics (incl negative/decimal),
     and figurative constants. Populates Property node values.

Tests: 145 passing (+2 ACCESSES from CALL USING) | TypeScript clean

* feat(cobol): implement Phase 2 — DECLARATIVES, SET, INSPECT, EXEC DLI

4 new extraction features for error handling, data flow, and IMS/DB:

2.1: EXEC DLI (IMS/DB) -> CodeElement + ACCESSES edges
     Accumulates EXEC DLI blocks like EXEC SQL. Parses DLI verbs
     (GU, GN, ISRT, REPL, DLET, CHKP, SCHD, TERM). Extracts
     SEGMENT, PCB, INTO/FROM, PSB. Creates dli-{verb} ACCESSES
     edges to <ims>:segment Record nodes.

2.2: DECLARATIVES / USE AFTER EXCEPTION -> ACCESSES edges
     Tracks inDeclaratives state. Detects USE AFTER STANDARD
     EXCEPTION ON file-name. Creates cobol-error-handler ACCESSES
     edge from handler section to file Record.

2.3: SET statement -> ACCESSES edges
     Detects SET TO TRUE (80-90% of SET usage) and SET index
     TO/UP BY/DOWN BY. Creates cobol-set-condition / cobol-set-index
     write edges + cobol-set-read for identifier values.

2.4: INSPECT -> ACCESSES edges with multi-line accumulator
     Accumulates INSPECT until period (like SORT). Extracts inspected
     field + tally counters. Creates cobol-inspect-read/write/tally
     edges. Form detection: tallying/replacing/converting/combined.

Preprocessor: 1398 -> 1597 LOC (+199). Tests: 145 passing.

* feat(cobol): implement Phase 3 — completeness fixes

6 partial features fixed to first-class support:

3.1: CALL RETURNING -> ACCESSES write edge (cobol-call-returning)
3.2: SELECT OPTIONAL flag preserved in FileDeclaration + Record node
3.3: ALTERNATE RECORD KEY extraction (matchAll for multiple keys)
3.4: COMMON attribute on nested programs (RE_PROGRAM_ID extended)
3.5: IS EXTERNAL / IS GLOBAL as first-class boolean properties
     (removed usage string hack)
3.6: AUTHOR / DATE-WRITTEN mapped to Module node description

Tests: 145 passing | TypeScript clean

* feat(cobol): implement Phase 4 — INITIALIZE + metadata completeness

4.1: INITIALIZE statement -> ACCESSES write edge (cobol-initialize)
4.2: DATE-COMPILED and INSTALLATION paragraphs extracted and mapped
     to Module node description alongside existing AUTHOR/DATE-WRITTEN

All 4 plan phases complete. Coverage: ~95% (up from 71.9%).
Tests: 145 passing | TypeScript clean

* test(cobol): add 24 unit tests for Phase 1-4 features

Coverage for all new extraction features:

Phase 1 (8 tests):
- EXEC SQL INCLUDE (unquoted, quoted, underscored)
- CALL USING (simple, mixed modes, ADDRESS OF, OMITTED)
- CALL RETURNING
- OCCURS DEPENDING ON
- VALUE clause (string, numeric, figurative constant)

Phase 2 (10 tests):
- EXEC DLI GU/ISRT/SCHD (verb, segment, PCB, INTO, FROM, PSB)
- DECLARATIVES USE AFTER EXCEPTION (single + multiple sections)
- SET TO TRUE, SET index UP BY
- INSPECT TALLYING, INSPECT REPLACING

Phase 3-4 (6 tests):
- SELECT OPTIONAL flag
- ALTERNATE RECORD KEY
- PROGRAM-ID IS COMMON
- IS EXTERNAL / IS GLOBAL booleans
- INITIALIZE extraction
- Full programMetadata (AUTHOR, DATE-WRITTEN, DATE-COMPILED, INSTALLATION)

Total: 168 tests passing (145 + 24 - 1 removed duplicate)

* fix(cobol): use /\r?\n/ split for Windows CRLF compatibility

All 4 COBOL source files now split on /\r?\n/ instead of '\n' to
handle CRLF line endings on Windows. Previously, trailing \r in
lines caused RE_GOTO's $ anchor to fail on multi-line GO TO
DEPENDING ON statements, producing only 1 goto edge instead of 4.

Files fixed: cobol-preprocessor.ts (2 sites), cobol-processor.ts,
jcl-parser.ts, cobol-copy-expander.ts

Tests: 168 passing | TypeScript clean

* fix(cobol): resolve 12th review — dynamic CALL/CANCEL dedup + trailing anchors

#1+#2: Removed incorrect hasQuotedCall/hasQuotedCancel deduplication
guards. RE_CALL_DYNAMIC and RE_CANCEL_DYNAMIC require [A-Z] after
CALL/CANCEL, so they CANNOT match quoted targets — the guards were
both unnecessary and actively harmful, suppressing dynamic CALL/CANCEL
in ON EXCEPTION patterns.

#3+#5: Changed RE_CALL_DYNAMIC and RE_CANCEL_DYNAMIC trailing anchor
from (?:\s|\.) to (?=\s|\.|$) (lookahead). The consuming anchor
failed when the identifier was the last token on a physical line.

Tests: 168 passing | TypeScript clean

* feat(cobol): add CALL accumulator + fix SORT double-statement (#4, #6)

Finding #4: Multi-line CALL USING accumulator
Added callAccum state variable that accumulates CALL statements
spanning multiple physical lines until period or END-CALL is found.
Uses flushCallAccum() to re-extract CALL target + USING parameters
from the full accumulated statement. This fixes the silent loss of
ACCESSES parameter edges when USING appears on lines after CALL.

Finding #6: SORT double-statement on same line
After flushSort(), the code now falls through to re-check the
current line for a new SORT/MERGE start (was previously blocked
by the sortAccum === null check evaluating before flushSort ran).

Also fixed: used non-global regex for CALL detection test to avoid
the classic global regex .test() lastIndex bug.

Tests: 168 passing (+1 ACCESSES from multi-line CALL USING)

* fix(cobol): resolve 13th review — CICS LOAD, USING extraction, file scoping

#1: CICS LOAD unresolved edge no longer silently deleted in second pass.
    Changed narrow cics-link/cics-xctl check to catch-all pattern:
    rel.reason?.startsWith('cics-') && rel.reason.endsWith('-unresolved')

#2: flushCallAccum USING extraction now stops before COBOL statement
    verbs (INSPECT, SEARCH, SORT, MERGE, DISPLAY, ACCEPT, MOVE, PERFORM,
    GO TO, CALL, IF, EVALUATE). Prevents absorbing adjacent statements
    as false USING parameters in legacy pre-COBOL-85 code without END-CALL.

#3: CICS FILE Record nodes now globally-scoped (<cics-file>:FILENAME)
    instead of per-file-scoped. Enables cross-program CICS file access
    analysis, consistent with SQL table scoping (<db>:TABLE).

#4: callAccum pre-check regex now has (?<![A-Z0-9-]) lookbehind to
    prevent false activation on compound identifiers like WS-CALL-FLAG.

Tests: 168 passing | TypeScript clean

* fix(cobol): resolve 14th review — callAccum false paragraph + Area A guard

#1: callAccum continuation lines now check for COBOL statement verb
    starts (GO TO, PERFORM, MOVE, etc.) and paragraph/section headers.
    If detected, the CALL is flushed as-is and the line processed
    normally — prevents false paragraph detection and currentParagraph
    corruption from lines like "WS-ADDR." being treated as paragraphs.

#4: callAccum pre-check now guarded by currentDivision === 'procedure'
    to prevent unnecessary activations in DATA DIVISION.

#5: Fixed-format paragraph detection now rejects lines with >7 leading
    spaces (Area B indentation) as paragraph candidates. Paragraph
    names in fixed-format must start in Area A (col 8-11, max 7 spaces).
    Free-format mode is unaffected.

Tests: 168 passing | TypeScript clean

* fix(cobol): resolve 15th review — callAccum Area A + verb boundary fixes

#A: Column-position-aware paragraph detection in callAccum flush.
#B: inspectAccum early-flush on paragraph/section/verb headers.
#C: Verb boundary \b → (?:\s|$) prevents MOVE-COUNT false flush.

* test(cobol): add 17 edge-case regression tests + fix USING verb boundary

17 new tests covering all recurring review patterns:

Multi-line CALL USING (7 tests):
- Parameters on separate continuation lines (IBM mainframe style)
- No absorption of INSPECT/GO TO/paragraphs following CALL
- END-CALL scope terminator
- Hyphenated identifiers (MOVE-COUNT) not triggering false flush
- Dual quoted+dynamic CALL on same line (ON EXCEPTION)

Nested program attribution (2 tests):
- CALL in inner program within inner line range
- PERFORM before first paragraph has null caller

CRLF compatibility (1 test):
- GO TO DEPENDING ON with \r\n line endings

Area A paragraph detection (2 tests):
- Area B (>7 spaces) rejected; Area A (7 spaces) accepted

SORT/MERGE (1 test): COLLATING SEQUENCE keywords not captured
PROCEDURE USING (2 tests): RETURNING excluded, period-terminated
Comment stripping (1 test): pipe in quoted string preserved
SELECT OPTIONAL (1 test): correct file name, not OPTIONAL keyword

Bug fix: USING extraction regex verb terminators changed from
\bVERB\b to \bVERB(?=\s|$) in flushCallAccum — prevents truncation
on hyphenated identifiers like MOVE-COUNT, PERFORM-LIMIT.

Total: 185 tests passing

* test(cobol): add 32 comprehensive edge-case regression tests

13 new describe blocks covering all extraction features:

- EXEC DLI: no-SEGMENT, multi-line accumulation (2 tests)
- SET: multiple targets, DOWN BY, TO numeric (3 tests)
- INSPECT: CONVERTING, multiple counters, tallying-replacing,
  paragraph flush during accumulation (4 tests)
- DECLARATIVES: no-STANDARD keyword, I-O mode, post-END paragraphs (3)
- COPY REPLACING: pseudotext deletion ==OLD== BY ==== (1 test)
- VALUE: hex literal, negative numeric, ALL literal (3 tests)
- OCCURS: TO range, fixed-size without DEPENDING ON (2 tests)
- Dynamic CALL/CANCEL: end-of-line, multiple CANCELs (3 tests)
- EXEC SQL: INCLUDE skips tables, SELECT INTO host vars, host
  variable extraction (3 tests)
- INITIALIZE: target and caller context (1 test)
- Nested programs: sibling scoping, PROGRAM-ID without ID DIV (2)
- EXEC EOF flush: unclosed EXEC SQL flushed (1 test)
- Multi-PERFORM: IF/ELSE dual PERFORM on single line (1 test)
- IS EXTERNAL: USAGE not polluted by external flag (1 test)

Total: 215 tests passing

* fix(cobol): resolve 16th review — CANCEL in CALL block + USING boundary

#1: flushCallAccum now extracts CANCEL statements from within CALL
    ON EXCEPTION blocks. Adds RE_CANCEL + RE_CANCEL_DYNAMIC matchAll
    passes alongside existing CALL extraction.

#2: Added \bCANCEL(?=\s|$) to USING lookahead regex to prevent CANCEL
    keyword being captured as false USING parameter.

#3: Multi-line CALL start now returns immediately to prevent the CALL
    start line from simultaneously feeding sortAccum/inspectAccum.

#6: Division transitions now flush all active accumulators (callAccum,
    sortAccum, inspectAccum) to prevent state leakage across programs.

Also added CANCEL to callAccum flush trigger verb list.

Tests: 215 passing | TypeScript clean

* refactor(cobol): extract shared verb constants + resolve 17th review

Extract COBOL_STATEMENT_VERBS, RE_STATEMENT_VERB_START, and
RE_USING_PARAMS as shared constants — eliminates 4 duplicated
25-verb regex patterns.

17th review: #1 flushCallAccum before EXEC entry, #2 inspectAccum
verb parity via shared constant.

Tests: 215 passing | TypeScript clean

* test(cobol): replace all fuzzy assertions with exact toBe checks

Replaced 7 toBeGreaterThan/toBeLessThan/toBeGreaterThanOrEqual
assertions with exact toBe values:

- dataItems.length: >= 3 → toBe(3)
- calls.length: >= 1 → toBe(1)
- calls[0].line: range check → toBe(10)
- programs[].startLine/endLine: comparison → exact values
- innerA.endLine/innerB.startLine: comparison → exact values

Also added 11 new edge-case tests (accumulator flush on EXEC/division
transitions, free-format, CANCEL in CALL block, SORT THRU, verb
flush, integration).

226 tests passing — zero fuzzy assertions remain.

* fix(cobol): resolve 19th review + 15 accumulator flush tests

Fixes:
#1: END PROGRAM flushes callAccum/sortAccum/inspectAccum
#2: PROGRAM-ID sibling path flushes all accumulators
#3: Added COMPUTE/ADD/SUBTRACT/MULTIPLY/DIVIDE/STRING/UNSTRING
    to COBOL_STATEMENT_VERBS (now 32 verbs)

Tests (15 new):
- END PROGRAM flush: single + nested programs (2)
- PROGRAM-ID sibling flush (1)
- Arithmetic verb flush: COMPUTE/ADD/SUBTRACT/MULTIPLY/DIVIDE (5)
- String verb flush: STRING/UNSTRING (2)
- Arithmetic not captured as false USING params (1)
- SORT flushed at END PROGRAM (1)
- INSPECT flushed at END PROGRAM (1)
- All with exact toBe assertions (2)

Total: 239 tests passing | Zero fuzzy assertions

* fix(cobol): resolve 20th review — INITIALIZE multi-target + 2 tests

Finding 1: INITIALIZE now captures multiple targets with REPLACING
clause keyword filtering. Regex changed to lazy match stopping at
REPLACING/WITH/period boundary. Targets split on whitespace and
filtered against INITIALIZE_CLAUSE_KEYWORDS set.

Tests (2 new):
- INITIALIZE multi-target: WS-CUSTOMER WS-ORDER WS-LINE-ITEM → 3
- INITIALIZE with REPLACING: only WS-RECORD captured, not keywords

Total: 241 tests passing | TypeScript clean
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant